#include <iostream>
#include <memory>
#include <list>
using namespace std;

//观察者模式
class Observer
{
public:
    virtual void update(int) = 0;
    virtual ~Observer() {}
};
class Subject
{
public:
    virtual void attach(Observer *) = 0;
    virtual void detach(Observer *) = 0;
    virtual void notify() = 0;
    virtual ~Subject() {}
};

class ConcreateSubject : public Subject
{
public:
    void attach(Observer *observer) override
    {
        if (observer)
        {
            _obList.push_back(observer);
        }
    }
    void detach(Observer *observer) override
    {
        if (observer)
        {
            _obList.remove(observer);
        }
    }
    void notify() override
    {
        for (auto &ob : _obList)
        {
            ob->update(_status);
        }
    }
    void setStatus(int status)
    {
        _status = status;
    }
    int getStatus() const
    {
        return _status;
    }

private:
    list<Observer *> _obList;
    int _status;
};


class ConcreateObserver : public Observer
{
public:
    ConcreateObserver(const string &name)
        : _name(name)
    {
    }
    void update(int value)
    {
        cout << "ConcreateObserver: " << _name << ", value =" << value << endl;
    }

private:
    string _name;
};
class ConcreateObserver2 : public Observer
{
public:
    ConcreateObserver2(const string &name)
        : _name(name)
    {
    }
    void update(int value)
    {
        cout << "ConcreateObserver2: " << _name << ", value =" << value << endl;
    }

private:
    string _name;
};
void test()
{
    unique_ptr<ConcreateSubject> psubject(new ConcreateSubject());
    unique_ptr<Observer> pObserver(new ConcreateObserver("zs"));
    unique_ptr<Observer> pObserver2(new ConcreateObserver2("ls"));
    psubject->setStatus(2);
    psubject->attach(pObserver.get());
    psubject->attach(pObserver2.get());
    psubject->notify();
    
    psubject->detach(pObserver2.get());
    psubject->setStatus(3);
    psubject->notify();
}
int main()
{
    test();
    return 0;
}
